<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>PREPARE</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="REFENTRY">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="sql-notify.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="sql-notify.html">快退</a></td><td width="60%" align="center" valign="bottom"></td><td width="10%" align="right" valign="top"><a href="sql-prepare-transaction.html">快进</a></td><td width="10%" align="right" valign="top"><a href="sql-prepare-transaction.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<h1><a name="SQL-PREPARE"></a>PREPARE</h1>
<div class="REFNAMEDIV"><a name="AEN52774"></a><h2>名称</h2>PREPARE&nbsp;--&nbsp;创建一个预备语句</div>
<a name="AEN52777"></a><a name="AEN52779"></a>
<div class="REFSYNOPSISDIV"><a name="AEN52782"></a><h2>语法</h2>
<pre class="SYNOPSIS">PREPARE <tt class="REPLACEABLE"><i>name</i></tt> [ (<tt class="REPLACEABLE"><i>datatype</i></tt> [, ...] ) ] AS <tt class="REPLACEABLE"><i>statement</i></tt></pre>
</div>
<div class="REFSECT1"><a name="AEN52787"></a><h2>描述</h2>
<p><tt class="COMMAND">PREPARE</tt> 创建一个预备语句。一个预备语句是服务器端的对象，可以用于优化性能。在执行 <tt class="COMMAND">PREPARE</tt> 语句的时候，指定的查询被分析、重写、规划。当随后发出 <tt class="COMMAND">EXECUTE</tt> 语句的时候，预备语句就只需要执行了。因此，分析、重写、规划阶段都只执行一次，而不是每次都要执行一次。</p>
<p>预备语句可以接受参数：在它执行的时候替换到查询中的数值。可以在一个预备语句里按照位置来引用参数，比如 <tt class="LITERAL">$1</tt>, <tt class="LITERAL">$2</tt> 等。可以指定一个相应的参数数据类型列表。如果一个参数的数据类型没有被指定或声明为 <tt class="LITERAL">unknown</tt> ，那么其类型将根据该参数所使用的实际上下文环境进行推测(如果有可能的话)。当执行该语句的时候，将在 <tt class="COMMAND">EXECUTE</tt> 语句中为这些参数指定实际值。参见 <a href="sql-execute.html"><i>EXECUTE</i></a> 获取更多信息。</p>
<p>预备语句只是在当前数据库会话的过程中存在。如果客户端退出，那么预备语句就会被遗忘，因此必须在被重新使用之前重新创建。这也意味着一个预备语句不能被多个数据库客户端同时使用；但是，每个客户端可以创建它们自己的预备语句来使用。预备语句可以用 <a href="sql-deallocate.html"><i>DEALLOCATE</i></a> 命令手工清除。</p>
<p>如果一个会话准备用于执行大量类似的查询，那么预备语句可以获得最大限度的性能优势。如果查询非常复杂，需要复杂的规划或者重写，那么性能差距将更加明显。比如，如果查询设计许多表的连接，或者有多种规则要求应用。如果查询的规划和重写相对简单，而执行起来开销相当大，那么预备语句的性能优势就不那么明显。</p>
</div>
<div class="REFSECT1"><a name="AEN52802"></a><h2>参数</h2>
<div class="VARIABLELIST">
<dl>
<dt><tt class="REPLACEABLE"><i>name</i></tt></dt>
<dd><p>给予这个特定的预备语句任意名字。它必须在一个会话中是唯一的，并且用于执行或者删除一个预备语句。</p></dd>
<dt><tt class="REPLACEABLE"><i>datatype</i></tt></dt>
<dd><p>预备语句的某个参数的数据类型。如果某个参数的数据类型未指定或指定为 <tt class="LITERAL">unknown</tt> ，那么将根据该参数使用的上下文环境进行推断。可以使用 <tt class="LITERAL">$1</tt>, <tt class="LITERAL">$2</tt> 等等在预备语句内部引用这个参数。</p></dd>
<dt><tt class="REPLACEABLE"><i>statement</i></tt></dt>
<dd><p><tt class="COMMAND">SELECT</tt>, <tt class="COMMAND">INSERT</tt>, <tt class="COMMAND">UPDATE</tt>, <tt class="COMMAND">DELETE</tt>, <tt class="COMMAND">VALUES</tt> 语句之一</p></dd>
</dl>
</div>
</div>
<div class="REFSECT1"><a name="AEN52828"></a><h2>注意</h2>
<p>在一些情况下，PostgreSQL 为一个预备语句生成的查询规划可能还不如按照普通方法提交并执行的查询生成的规划好。这是因为该查询在被规划的时候(也是优化器判断最优查询规划的时候)，在查询中声明的任何参数的实际数值都还不可见。PostgreSQL 在表中收集数据分布的统计，而且可以利用查询中的常量来猜测执行查询的可能结果。因为这些数据在规划的时候还是未知，所以，得到的规划可能很差劲。使用 <a href="sql-explain.html"><i>EXPLAIN</i></a> 查看 PostgreSQL 为预备语句选取的查询计划。</p>
<p>有关查询规划和 PostgreSQL 为查询优化的目的收集统计的更多信息，参阅 <a href="sql-analyze.html"><i>ANALYZE</i></a> 文档。</p>
<p>可以通过查询 <a href="view-pg-prepared-statements.html"><tt class="STRUCTNAME">pg_prepared_statements</tt></a> 系统试图获得某个会话中所有可用的预备语句</p>
</div>
<div class="REFSECT1"><a name="SQL-PREPARE-EXAMPLES"></a><h2>例子</h2>
<p>为一个 <tt class="COMMAND">INSERT</tt> 语句创建一个预备语句然后执行它：</p>
<pre class="PROGRAMLISTING">PREPARE fooplan (int, text, bool, numeric) AS
    INSERT INTO foo VALUES($1, $2, $3, $4);
EXECUTE fooplan(1, 'Hunter Valley', 't', 200.00);</pre>
<p>为一个 <tt class="COMMAND">SELECT</tt> 语句创建一个预备语句然后执行它：</p>
<pre class="PROGRAMLISTING">PREPARE usrrptplan (int) AS
    SELECT * FROM users u, logs l WHERE u.usrid=$1 AND u.usrid=l.usrid
    AND l.date = $2;
EXECUTE usrrptplan(1, current_date);</pre>
<p>注意，第二个参数的数据类型并未指定。所以将从上下文环境推测 <tt class="LITERAL">$2</tt> 的类型。</p>
</div>
<div class="REFSECT1"><a name="AEN52849"></a><h2>兼容性</h2>
<p>SQL 标准包含一个 <tt class="COMMAND">PREPARE</tt> 语句，但是它只用于嵌入式 SQL 。PostgreSQL 实现的 <tt class="COMMAND">PREPARE</tt> 语句的语法也略有不同。</p>
</div>
<div class="REFSECT1"><a name="AEN52854"></a><h2>又见</h2><a href="sql-deallocate.html"><i>DEALLOCATE</i></a>, <a href="sql-execute.html"><i>EXECUTE</i></a></div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="sql-notify.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="sql-prepare-transaction.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">NOTIFY</td><td width="34%" align="center" valign="top"><a href="sql-commands.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">PREPARE TRANSACTION</td></tr>
</table>
</div>
</body></html>